<?php

namespace addons\cloud_market\utils;

use hiduoke\services\Random;
use think\facade\Cache;

/**
 * CloudMarket Token管理工具类
 * 统一管理用户登录token的生成、验证、删除等操作
 */
class CloudMarketToken
{
    /**
     * Token缓存前缀
     */
    const TOKEN_PREFIX = 'token_';

    /**
     * 用户Token列表缓存前缀
     */
    const USER_TOKENS_PREFIX = 'user_tokens_';

    /**
     * 默认Token有效期（秒）
     */
    const DEFAULT_EXPIRE = 2592000; // 30天

    /**
     * 生成并设置Token
     *
     * @param int $uid 用户ID
     * @param int $expire 过期时间(秒)，默认30天
     * @return string 生成的token
     */
    public static function generate($uid, $expire = self::DEFAULT_EXPIRE)
    {
        $token = Random::uuid();
        self::set($token, $uid, $expire);
        return $token;
    }

    /**
     * 设置Token
     *
     * @param string $token Token值
     * @param int $uid 用户ID
     * @param int $expire 过期时间(秒)
     * @return bool
     */
    public static function set($token, $uid, $expire = self::DEFAULT_EXPIRE)
    {
        $data = [
            'uid' => $uid,
            'expire' => time() + $expire,
            'create_time' => time()
        ];

        // 设置token缓存
        $result = Cache::set(self::TOKEN_PREFIX . $token, $data, $expire);
        // 将token添加到用户token列表中（用于批量清除）
        if ($result) {
            self::addToUserTokens($uid, $token, $expire);
        }

        return $result;
    }

    /**
     * 获取Token数据
     *
     * @param string $token Token值
     * @return array|null
     */
    public static function get($token)
    {
        $data = Cache::get(self::TOKEN_PREFIX . $token);
        // 检查是否过期
        if ($data && isset($data['expire']) && $data['expire'] < time()) {
            self::delete($token);
            return null;
        }
        return $data;
    }

    /**
     * 验证Token是否有效
     *
     * @param string $token Token值
     * @return bool
     */
    public static function check($token)
    {
        $data = self::get($token);
        return $data !== null && isset($data['uid']);
    }

    /**
     * 获取Token对应的用户ID
     *
     * @param string $token Token值
     * @return int|null
     */
    public static function getUid($token)
    {
        $data = self::get($token);
        return $data ? $data['uid'] : null;
    }

    /**
     * 删除Token
     *
     * @param string $token Token值
     * @return bool
     */
    public static function delete($token)
    {
        // 获取token数据以便从用户token列表中移除
        $data = Cache::get(self::TOKEN_PREFIX . $token);
        if ($data && isset($data['uid'])) {
            self::removeFromUserTokens($data['uid'], $token);
        }

        return Cache::delete(self::TOKEN_PREFIX . $token);
    }

    /**
     * 清除用户所有Token
     *
     * @param int $uid 用户ID
     * @return bool
     */
    public static function clear($uid)
    {
        $userTokens = Cache::get(self::USER_TOKENS_PREFIX . $uid);

        if ($userTokens && is_array($userTokens)) {
            foreach ($userTokens as $token) {
                Cache::delete(self::TOKEN_PREFIX . $token);
            }
        }

        // 清除用户token列表
        return Cache::delete(self::USER_TOKENS_PREFIX . $uid);
    }

    /**
     * 刷新Token过期时间
     *
     * @param string $token Token值
     * @param int $expire 新的过期时间(秒)
     * @return bool
     */
    public static function refresh($token, $expire = self::DEFAULT_EXPIRE)
    {
        $data = self::get($token);
        if (!$data) {
            return false;
        }

        return self::set($token, $data['uid'], $expire);
    }

    /**
     * 获取用户所有有效Token
     *
     * @param int $uid 用户ID
     * @return array
     */
    public static function getUserTokens($uid)
    {
        $userTokens = Cache::get(self::USER_TOKENS_PREFIX . $uid);
        $validTokens = [];
        if ($userTokens && is_array($userTokens)) {
            foreach ($userTokens as $token) {
                if (self::check($token)) {
                    $validTokens[] = $token;
                }
            }

            // 更新用户token列表，移除无效token
            if (count($validTokens) !== count($userTokens)) {
                Cache::set(self::USER_TOKENS_PREFIX . $uid, $validTokens, self::DEFAULT_EXPIRE);
            }
        }

        return $validTokens;
    }

    /**
     * 将token添加到用户token列表
     *
     * @param int $uid 用户ID
     * @param string $token Token值
     * @param int $expire 过期时间
     * @return bool
     */
    protected static function addToUserTokens($uid, $token, $expire)
    {
        $userTokens = Cache::get(self::USER_TOKENS_PREFIX . $uid) ?: [];

        if (!in_array($token, $userTokens)) {
            $userTokens[] = $token;
            return Cache::set(self::USER_TOKENS_PREFIX . $uid, $userTokens, $expire);
        }

        return true;
    }

    /**
     * 从用户token列表中移除token
     *
     * @param int $uid 用户ID
     * @param string $token Token值
     * @return bool
     */
    protected static function removeFromUserTokens($uid, $token)
    {
        $userTokens = Cache::get(self::USER_TOKENS_PREFIX . $uid);

        if ($userTokens && is_array($userTokens)) {
            $userTokens = array_filter($userTokens, function($t) use ($token) {
                return $t !== $token;
            });

            if (empty($userTokens)) {
                return Cache::delete(self::USER_TOKENS_PREFIX . $uid);
            } else {
                return Cache::set(self::USER_TOKENS_PREFIX . $uid, array_values($userTokens), self::DEFAULT_EXPIRE);
            }
        }

        return true;
    }

    /**
     * 清理所有过期Token
     * 建议在定时任务中调用
     *
     * @return int 清理的token数量
     */
    public static function cleanExpired()
    {
        // 注意：这个方法需要根据具体的缓存驱动实现
        // 如果使用Redis，可以使用SCAN命令遍历所有token
        // 如果使用文件缓存，需要遍历缓存文件
        // 这里提供一个基础实现框架

        $cleaned = 0;
        // TODO: 根据实际缓存驱动实现过期token清理逻辑

        return $cleaned;
    }
}
